package main

import (
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"reflect"
	"time"
)

// StructToHexBytes 将任意结构体或结构体数组转换为16进制字节数组
func StructToHexBytes(data interface{}) ([]byte, error) {
	value := reflect.ValueOf(data)

	// 如果是结构体数组，则逐个处理
	if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
		var result []byte
		for i := 0; i < value.Len(); i++ {
			element := value.Index(i)
			elementBytes, err := structToBytes(element.Interface())
			if err != nil {
				return nil, err
			}
			result = append(result, elementBytes...)
		}
		return result, nil
	}

	// 如果是单个结构体，则直接处理
	if value.Kind() == reflect.Struct {
		return structToBytes(data)
	}

	return nil, fmt.Errorf("Input must be a struct or struct array")
}

// structToBytes 将单个结构体转换为16进制字节数组
func structToBytes(data interface{}) ([]byte, error) {
	value := reflect.ValueOf(data)
	if value.Kind() != reflect.Struct {
		return nil, fmt.Errorf("Input must be a struct")
	}

	var result []byte

	for i := 0; i < value.NumField(); i++ {
		field := value.Field(i)

		switch field.Kind() {
		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			result = append(result, uintToBytes(field.Uint())...)
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			result = append(result, intToBytes(field.Int())...)
		case reflect.String:
			result = append(result, []byte(field.String())...)
		case reflect.Interface:
			strValue := fmt.Sprintf("%v", field.Interface())
			result = append(result, []byte(strValue)...)
		case reflect.Array, reflect.Slice:
			for j := 0; j < field.Len(); j++ {
				result = append(result, uintToBytes(field.Index(j).Uint())...)
			}
		default:
			return nil, fmt.Errorf("Unsupported field type: %v", field.Kind())
		}
	}

	return result, nil
}

// uintToBytes 将uint类型转换为16进制字节数组
func uintToBytes(num uint64) []byte {
	bytes := make([]byte, 8)
	for i := 7; i >= 0; i-- {
		bytes[i] = byte(num & 0xFF)
		num >>= 8
	}
	return bytes
}

// intToBytes 将int类型转换为16进制字节数组
func intToBytes(num int64) []byte {
	bytes := make([]byte, 8)
	for i := 7; i >= 0; i-- {
		bytes[i] = byte(num & 0xFF)
		num >>= 8
	}
	return bytes
}

// HexBytesToStruct 将16进制字节数组转换为结构体
func HexBytesToStruct(data []byte, exampleStructType reflect.Type) (interface{}, error) {
	result := reflect.New(exampleStructType).Interface()
	resultValue := reflect.ValueOf(result).Elem()

	offset := 0
	for i := 0; i < resultValue.NumField(); i++ {
		field := resultValue.Field(i)

		switch field.Kind() {
		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			fieldValue, bytesRead := bytesToUint(data[offset:])
			field.SetUint(fieldValue)
			offset += bytesRead
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			fieldValue, bytesRead := bytesToInt(data[offset:])
			field.SetInt(fieldValue)
			offset += bytesRead
		case reflect.String:
			fieldValue, bytesRead := bytesToString(data[offset:])
			field.SetString(fieldValue)
			offset += bytesRead
		case reflect.Interface:
			fieldValue, bytesRead := bytesToInterface(data[offset:], field.Type())
			field.Set(reflect.ValueOf(fieldValue))
			offset += bytesRead
		case reflect.Array, reflect.Slice:
			for j := 0; j < field.Len(); j++ {
				elementValue, bytesRead := bytesToUint(data[offset:])
				field.Index(j).SetUint(elementValue)
				offset += bytesRead
			}
		default:
			return nil, fmt.Errorf("Unsupported field type: %v", field.Kind())
		}
	}

	return result, nil
}

// bytesToUint 从字节数组中解析出uint类型的值
func bytesToUint(data []byte) (uint64, int) {
	value := binary.BigEndian.Uint64(data)
	return value, 8
}

// bytesToInt 从字节数组中解析出int类型的值
func bytesToInt(data []byte) (int64, int) {
	value := int64(binary.BigEndian.Uint64(data))
	return value, 8
}

// bytesToString 从字节数组中解析出string类型的值
func bytesToString(data []byte) (string, int) {
	if len(data) < 4 {
		return "", 0
	}

	length := binary.BigEndian.Uint32(data)
	if len(data) < int(4+length) {
		return "", 0
	}

	value := string(data[4 : 4+length])
	return value, int(4 + length)
}

// bytesToInterface 从字节数组中解析出interface{}类型的值
func bytesToInterface(data []byte, fieldType reflect.Type) (interface{}, int) {
	// 简单处理，将值转换为字符串
	strValue, bytesRead := bytesToString(data)
	return strValue, bytesRead
}

func main() {

	t := time.Now().Unix()

	// 示例结构体 A
	type ExpA struct {
		Uid        string
		UpdateTime int64
	}

	// 示例结构体 B
	type ExpB struct {
		SN         string
		UpdateTime int64
	}

	// 示例结构体 Exp
	type Exp struct {
		ID   uint32
		Name string
		Age  int
		Code int64
		Obj  interface{}
	}

	A := []ExpA{{Uid: "1.6.16.1.5.", UpdateTime: t}, {Uid: "2.6.16.1.5.", UpdateTime: t}}
	B := []ExpB{{SN: "1-6-16-1-5-", UpdateTime: t - 40000}, {SN: "2-6-16-1-5-", UpdateTime: t - 50000}}
	CA := Exp{ID: 123, Name: "John Doe", Age: 30, Code: t, Obj: A}
	CB := Exp{ID: 123, Name: "John Doe", Age: 30, Code: t, Obj: B}

	bytes, err := StructToHexBytes(CA)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 打印结果
	fmt.Printf("CA :%#v\n Hex CA: %20x\n",CA , bytes)

	bytes, err = StructToHexBytes(CB)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}

	// 打印结果
	fmt.Printf("CB :%#v\n Hex CB: %s\n" ,CB , hex.EncodeToString(bytes))

}
